package ch.zhaw.skuh.turing.model.turingmaschine;

import ch.zhaw.skuh.turing.controller.Factory;

public class AddSkript extends TuringChar {

	private static int COUNTSTATES = 4;
	private static int[] ACCEPT = { 3 };

	private static int TAPES = 1;

	private static String NAME = "Add.-Skript";

	// shortcuts
	private static String B = "_";
	private static String O = "0";
	private static String I = "1";

	// Alphabet: "Blank" must be in first position!
	private static String ABC = B + O + I;

	// creation as arrays (we might use more tapes later)
	private static int[] R = { 1 };
	@SuppressWarnings("unused")
	private static int[] L = { -1 };

	// the calculated result
	private int calcResult = 0;

	public AddSkript() {
		super(COUNTSTATES, ABC, B.toCharArray()[0], ACCEPT, TAPES, NAME);
	}

	private void initRules() {
		// short-hand notation (watch static values!)
		// Example:
		// (q0, 1) > (q0, 1, R)
		// short for:
		// addRule(0, "1", 0, "1", +1);
		// shorter, with static vars mapped to alphabet positions
		// addRule(0, I, 0, I, R);
		// meaning (q0, 1) -> (q0, 1, >)

		// *** q0 rules ***
		super.addRule(0, O, 1, B, R);
		super.addRule(0, I, 2, B, R);
		
		// *** q1 rules ***
		super.addRule(1, O, 1, O, R);
		super.addRule(1, I, 2, O, R);
		
		// *** q2 rules ***
		super.addRule(2, O, 2, O, R);
		super.addRule(2, I, 3, B, R);
		
		// *** q3 rules ***
		// no rules, accpepted state from (q0, B)
	}

	@Override
	public boolean validateInput(String text) {
		if(!Factory.validateNumberList(text, Factory.DELIMITER)){
			return false;
		}
		return ( Factory.toNumber(text, Factory.DELIMITER).length < 3);
	}

	@Override
	public boolean isOutputEnabled() {
		return true;
	}

	@Override
	public void setTapes(String input) {
		long[] list = Factory.toNumber(input, Factory.DELIMITER);
		StringBuilder sb = new StringBuilder();
		this.calcResult = 0;
		for (int i = 0; i < list.length; i++) {
			// calc result
			this.calcResult += list[i];
			// fill tape
			for (int j = 0; j < list[i]; j++) {
				sb.append(O);
			}
			// delimiter char
			sb.append(I);
		}
		// only 1 tape
		char[][] charInput = new char[1][];
		charInput[0] = sb.toString().toCharArray();
		// call super class method (which handles the rest)
		setTapes(charInput);
		//rules cannot be added until now
		initRules();
	}

	@Override
	public String getResult() {
		if (getMaschine().hasRule()) {
			return null;
		} else {
			String s = getTape(0);
			int result = Factory.count(s, '0');
			return Integer.toString(result);
		}
	}

	@Override
	public String getResultPrediction() {
		return Integer.toString(this.calcResult);
	}

}
